package com.alibaba.dubbo.common.inet.ipv4;

import java.net.InetAddress;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.regex.Pattern;

import com.alibaba.dubbo.common.inet.IPMatcherException;
import com.alibaba.dubbo.common.inet.InetAddressMatcher;
import com.alibaba.dubbo.common.inet.InetAddressProvider;


 /**
  * 
  * @author kingbo.ruan
  * 2014年9月25日 上午6:57:35
  */
public class AddressMatcher implements InetAddressMatcher {
	
	public AddressMatcher(){
		
	}
	
	public AddressMatcher(String addr){
		this.addAddress(addr);
	}
	
	static final Pattern IPv4 = Pattern.compile("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
	/*
	static final Pattern IPv4Range = 
			Pattern.compile("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\s*\\-\\s*(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
	*/
	static final Pattern IPv4Wildcard = Pattern.compile("^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])|\\*)\\.){0,3}(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])|\\*)$");
	
	
	public void setInetAddressProvider(InetAddressProvider provider){
		if(provider != null){
			Iterator<String> it = provider.getInetAddressIterator();
			if(it != null){
				while(it.hasNext()){
					String s = it.next();
					if(s != null && s.length() > 0){
						this.addAddress(s);
					}
				}
			}
		}
	}
	
	public void addInetAddressProvider(InetAddressProvider provider){
		if(provider != null){
			Iterator<String> it = provider.getInetAddressIterator();
			if(it != null){
				while(it.hasNext()){
					String s = it.next();
					if(s != null && s.length() > 0){
						this.addAddress(s);
					}
				}
			}
		}
	}
	
	public void setAddress(String addr){
		this.addAddress(addr);
	}
	
	public void addAddress(String addr){
		if(addr == null || addr.length() == 0) return;
		StringTokenizer tokens = new StringTokenizer(addr, "\t\r\n\f,;");
		while(tokens.hasMoreTokens()){
			String token = tokens.nextToken();
			token = token.trim();
			if(token == null || token.length() == 0) continue;
			if(IPv4.matcher(token).matches()){
				InetAddressMatcher matcher = new EqMatcher(token);
				this.matchers.add(matcher);
			}else if(IPv4Wildcard.matcher(token).matches()){
				InetAddressMatcher matcher = new WildcardEqMatcher(token);
				this.matchers.add(matcher);
			}else{
				String[] parts = token.split("\\-");
				if(parts != null && parts.length == 2){
					InetAddressMatcher matcher = new RangeMatcher(parts[0].trim(), parts[1].trim());
					this.matchers.add(matcher);
				}else{
					throw new IPMatcherException("Malformed IP specification " + token);
				}
			}
		}
	}
	

	Vector<InetAddressMatcher> matchers = new Vector<InetAddressMatcher>();
	
	@Override
	public boolean match(InetAddress address) {
		//如果有多个地址，优先选择非无线的网址
		for(InetAddressMatcher matcher : matchers){
			if(matcher.match(address)) return true;
		}
		return false;
	}

	@Override
	public InetAddress select(InetAddress[] addresses) {
		for(InetAddressMatcher matcher: matchers){
			for(InetAddress address : addresses){
				if(matcher.match(address)) return address;
			}
		}
		return null;
	}

}
